structure Temp : TEMP =
struct
  structure ErrorMsg = ErrorMsg
  val labels = ref (~1)
  fun newLabel () =
      let val _ = (labels := (!labels) + 1)
      in  ".L"^(Int.toString(!labels))
      end
  fun resetLabel () =
      labels := (~1)

  val var_tmps = ref(~1)

  fun new_var () =
      let val _ = (var_tmps := (!var_tmps) + 1)
      in  "H"^(Int.toString (!var_tmps))
      end

  fun reset_var () = 
      var_tmps := (~1)
  
  val nums = ref 3
  fun newNum () =
      let val _ = nums := ((!nums) + 1)
      in  (!nums)
      end
  fun reset_num () =
      nums := 3

  val ptr_temps = ref (~1)
  fun new_ptr () =
      let val _ = (ptr_temps := (!ptr_temps) + 1)
      in  "hack_ptr_"^(Int.toString(!ptr_temps))
      end
  
  val asst_tmp = ref(~1)
  fun new_asst l =
      let val _ = (asst_tmp := (!asst_tmp) + 1)
      in  "..A"^(Int.toString(!asst_tmp))^"_"^l
      end
  fun reset_asst () = asst_tmp := (~1)

  val Vlab : int ref = ref 0
  fun new_V str = 
      let val t = !Vlab
	  val _ = Vlab := !Vlab + 1
      in str^Int.toString(t)
      end

  fun reset_V () = Vlab := 0 
 
  val si : int ref = ref 2
  fun new_si () = 
      let val _ = si := !si + 1
      in  !si
      end

  fun reset_si () = si := 2  
     
  fun reset () = 
      (
      labels := (~1);
      ptr_temps := (~1);
      var_tmps := (~1);
      nums := (~1);
      asst_tmp := (~1);
      reset_V ();
      reset_si ())

  fun gen_name' pos (a::rest, n) = 
      if a < pos 
      then (Int.toString n, Int.toString (pos-a))
      else gen_name' pos (rest, n-1)
    | gen_name' pos _ = ("0", "0")

  fun gen_name pos = 
      let val (ln, hn) = gen_name' pos (!(ErrorMsg.linePos), !(ErrorMsg.lineNum))
      in "_"^ln^"_"^hn
      end      
end
